package com.btb.adapter.service;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.Event;
import org.web3j.abi.datatypes.generated.Uint256;
import org.web3j.protocol.core.methods.response.TransactionReceipt;

import com.btb.adapter.constant.Constants;
import com.btb.adapter.mapper.UpChainHeroMapper;
import com.btb.adapter.model.TransferRecord;
import com.btb.adapter.model.TransferRecordExample;
import com.btb.adapter.model.UpChainHero;
import com.btb.adapter.model.UpChainHeroExample;
import com.btb.adapter.vo.TransactionReceiptEx;

/**
 * @author hqbzl
 *
 *         上链的事件处理
 *
 */
@Service
public class UpChainEventService {
	@Autowired
	private ChainblockEventService chainblockEventService;

	@Value("${adapter.contract.chainup.hero}")
	private String chainupHeroAddress;

	private final Event HERO_UP_CHAIN = new Event(Constants.UP_CHAIN_HERO_EVENT,
			Arrays.asList(new TypeReference<Address>() {
	}, new TypeReference<Address>() {
	}, new TypeReference<Uint256>() {
	}, new TypeReference<Uint256>() {
	}));
	@Autowired
	private UpChainHeroMapper upChainHeroMapper;

	@Transactional(rollbackFor = Exception.class)
	public boolean event(String startBlockNumber, String endBlockNumber) {
		List<TransactionReceiptEx> list = chainblockEventService.event(chainupHeroAddress, HERO_UP_CHAIN, startBlockNumber, endBlockNumber);
		for (TransactionReceiptEx x : list) {
			TransactionReceipt transactionReceipt = x.getTransactionReceipt();
			if(Objects.isNull(transactionReceipt)) {
				continue;
			}
			UpChainHero selectOne = selectOne(transactionReceipt.getTransactionHash());
			// 说明是第一次收到事件
			if(Objects.nonNull(selectOne)) {
				update(x);
			}
		}
		return false;
	}
	private int update(final TransactionReceiptEx transactionReceipt) {
		TransactionReceipt transaction = transactionReceipt.getTransactionReceipt();
		final String transactionHash = transaction.getTransactionHash();
		boolean statusOK = transaction.isStatusOK();
		String status = Constants.UP_CHAIN_STATUS_TWO;
		if(Objects.equals(true, statusOK)) {
			status = Constants.UP_CHAIN_STATUS_THREE;
		}
		UpChainHero record = UpChainHero.builder()
				.transactionHash(transactionHash)
				.eventUpChainTimestamp(Long.parseLong(transactionReceipt.getTimestamp()))
				.status(status)
				.build();
		UpChainHeroExample example = new UpChainHeroExample();
		example.createCriteria().andTransactionHashEqualTo(transactionHash);
		return upChainHeroMapper.updateByExampleSelective(record, example);
	}
	private UpChainHero selectOne(final String transactionHash) {
		UpChainHeroExample example = new UpChainHeroExample();
		example.createCriteria().andTransactionHashEqualTo(transactionHash);
		List<UpChainHero> selectByExample = upChainHeroMapper.selectByExample(example);
		return selectByExample.stream().findAny().orElse(null);
	}
}
